Reference Parameters
Before we get to arrays, there’s a small but important concept that you should be familiar with: reference parameters. In the past, I’ve emphasized how the formal parameters of your functions are simply copies of the actual parameters passed into the function. However, if you define a parameter as a reference parameter, how it is changed within the function will actually change the value that was passed into it. For example, if you passed an integer variable by reference from your main function, after the function, the variable—in main—could hold a different value.
The syntax to declare a reference parameter is exactly the same as a normal parameter, except that you add an ampersand before the parameter name. Also remember to also include it in the function prototype.
void refFunction(int &refer); main() { int variable = 5; cout << “Variable before function: “ << variable << endl; // will be 5 refFunction(variable); refFunction << “Variable after function: “ << variable << endl; // will be 10 } void refFunction(int &refer) { refer += 5; }
This short example will first output the value 5, as you would expect. However, after the function is called, the value will actually be changed within main, and the program will output the value 10.
Concept of Arrays
Now, on to another important concept of programming—arrays! Arrays allow you to contain more than one piece of data within a variable. They’re quite simple: an array is essentially a collection of a type of variable. For example, you could have an array of 10 integers, meaning you can store 10 integer values in that one array. We'll learn more about how they are stored in lesson 10.
Declaring Arrays
Arrays are declared in the same way as variables, except with the addition of square brackets. As with normal variables, you first specify the type of your variable (int, double, char, etc). Then, add your identifier, and finally the array size in square brackets at the end of the identifier.
Additionally, when you declare an array of a fundamental type (and only when you declare it), you can set all values to a certain initial value by adding “= {value}” to your declaration.
int integerArray[50];
Declares an array of 50 integers
char characterArray[10] = {‘a’};
Declares an array of 10 characters, and initializes all of them to ‘a.'
Using Arrays
Accessing data within an array is also quite simple. To access an element in the array, simply write the array’s identifier followed by brackets with the position of the element in the array. The positions of the elements, referred to as indices, always begin at 0. This means that the first element in the array is at index 0, the second at 1, and so on. The final element is stored at the index of your array's total size minus one.
While it may be tempting to simply set one array identifier equal to another to copy the data, this is not allowed (again, see lesson 10). Hence, if you want to cope one array to another, you must loop through it and copy each element individually.
Working with arrays is a big source of errors for beginning programmers, as the process is susceptible to many “off-by-one” errors. However, that's not all: if you try to access or assign a value that is past the end of an array or before it begins, you may or may not generate an error, but it will always be a bug. You won’t always generate an error because if you go off the end of an array, you will start assigning values to whatever memory was after the end of your array. If that memory was used by the operating system, your program will throw an error known as a segmentation fault, or seg fault for short. People tend to have a love/hate relationship with seg faults, as if you have one, it’s good to know that you have a bug, and it's relatively easy to find where the error is. However, they’re also bad—they might mean that you have other seg faults waiting to happen, but haven’t—remember that going into memory past or before your array might not cause your program to crash. To top it all off, the memory arrangement will be different on different computers, so your program may behave differently. If there’s anything to take from all this, just remember to be very diligent in looking for errors when using array.
If you are using linux, the utility valgrind is extremely useful in memory profiling and finding segmentation faults (also memory leaks, see lesson 11).
integerArray[0] = 5;
Sets the first element in the array to 5.
characterArray[5] = ‘l’;
Sets the sixth element in the array to ‘l.’
char testValue = characterArray[10];
This example will try to access the 11th element in the array, when it only contains 10 values. Hence, it will try to read the memory after your array, and might throw a segmentation fault.
Arrays and Loops
The ability to assign values to individual elements in an array is useful, but most the array processing you’ll be doing will be using loops. There isn’t anything new to learn here, but realize that you can apply loops in many ways: for example, loop from 0 to your array size, and assign a value to each element in the array using your counter variable. This is one of the ways that the "for" loop is most useful. Finally, remember to be careful of off-by-one errors—for example, if the first example looped until "i" was less than or equal to 10, in the last iteration it would try to access array[10], the 11th element—possibly causing an error.
for(int i = 0; i < 50; i++) integerArray[i] = 0;
This example simply loops through each element in a 50 integer array and sets it to 0.
for(int i = 0; i < 10; i++) characterArray[i] += i;
This example will loop through each element of the array, adding adding an increasing amount to each one (i.e. add zero to the first element, so it will remain ‘a’, add one to the second element, so it will be ‘b’, etc.).
Array Parameters
When you pass an array to a function, it will automatically act like a reference parameter, even if you don’t use the ampersand. Because of this, remember that when you pass arrays to functions, the function will change the values of the array within main.
To pass an array to a function, you must first make it clear that your function will take an array: in the prototype, simply type a pair of empty square brackets. You don’t actually have to specify the size of the array when you pass it to a function, it just has to know that the data will be an array. You do the same in the function implementation, and finally, when calling the function with actual parameters, simply type the array identifier without any brackets at all.
void clearArray(int array[],int size); main() { int integerArray[10]; clearArray(integerArray,10); } void clearArray(int array[], int size) { for(int I = 0; I < size; I++) array[i] = 0; } }
C-Strings
The final subtopic in this section covers C-Style strings, or just c-strings for short. C-strings are technically just arrays of characters and have specific ways of working with them. The basic principle is quite simple—the array holds the characters of the string, and is "null-terminated." This means that a null character (‘\0’) must always signify the end of the string. Because of this property, the size of the array must always be at least one more than the number of actual characters in your string.
You can use C-Strings how you would expect a string type to work: for example, you can cin to a c-string and your program will automatically copy the input word to the array, adding a null character to the end. When you use a c-string like that, it is called using it in the aggregate.
Finally, you can easily do character-by-character manipulation of c-strings, as you know that you have reached the end of the string when you find a null character. We won’t be going very in-depth with c-strings here (see lesson 11), but you should learn how to declare and use them.
char cstring[50];
The first example declares a c-string that can hold 50 characters. Because at least one element must contain the null character, it can hold 49 "real" characters.
cin >> cstring;
This will input one word from the console and store it in the array named "cstring," automatically adding a null character after the word.
for(int i = 0; cstring[i]; i++) cout << cstring[i] << endl;
The final example will loop through the array "cstring" until it comes to a null character (you can simply use the character as the conditional statement, as it will evaluate to true if it is anything but null) and output each character on a new line.